package de.bht.cge.flightsim.game;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;

import de.bht.cge.flightsim.util.Helper;
import de.bht.cge.flightsim.util.Settings;
import de.bht.jvr.core.CameraNode;
import de.bht.jvr.core.DirectionalLightNode;
import de.bht.jvr.core.GroupNode;
import de.bht.jvr.core.PickRay;
import de.bht.jvr.core.Picker;
import de.bht.jvr.core.PickingResult;
import de.bht.jvr.core.Printer;
import de.bht.jvr.core.Transform;
import de.bht.jvr.core.pipeline.Pipeline;
import de.bht.jvr.core.pipeline.PipelineCommandPtr;
import de.bht.jvr.math.Vector3;

/**
 * 
 * @author Dennis, Benni
 *
 */
public class Scene 
{	
	private GroupNode rootNode;

	private CameraNode camera;
	private Pipeline pipeline;
	private Skybox skybox;
	private Plane plane;
	private GroundBuilder ground;	
	private Cloud cloud;	
	
	private PipelineCommandPtr ptr;
	public static GroupNode PickingGroundNode = new GroupNode();
	private int height = 0;

	public Scene()
	{
		
	}
	
	public void UpdateSkybox()
	{
		this.skybox.setTransform(Transform.translate(Helper.GetNodeTranslationVector(this.camera)));
	}
	
	
	public void UpdateGround()
	{
		this.getGround().testPosition(this.getCamera().getTransform().getMatrix().translation());
	}	
	
	public void UpdateHeight()
	{		
		Vector3 camPos = this.camera.getTransform().getMatrix().translation();
		PickRay ray = new PickRay(camPos, new Vector3(0,-1,0));
		
		PickingResult result = Picker.pickShapeNode(Scene.PickingGroundNode, ray, "(?!Skybox.*).*"); // ignore sky box
		
		if(result.getPickingPoint() != null)
		{
			Vector3 v = result.getPickingPoint().sub(camPos);
			this.height =  (int)v.length();
			
		}
		else
		{
		    Vector3 v = this.camera.getTransform().getMatrix().translation();
		    v.add(new Vector3(0,200,20));
			this.camera.setTransform(Transform.translate(v));
		}		
	}
	
	public void UpdateVegetation()
	{
	    Vector3 camPos = this.camera.getTransform().getMatrix().translation();
	    ground.setTreeEnabled(false);
        ground.getNearestGround(camPos).setTreeEnabled(true);
	}
	
	public void BuildScene(float rX, float rY, float rZ)
	{
		this.rootNode = new GroupNode("Root");
		
		try 
		{
			this.setupCamera(rX, rY, rZ);
			
			//Lichteinstellungen
			DirectionalLightNode dLight = new DirectionalLightNode();
	        dLight.setTransform(Transform.rotateXDeg(-80));
	        this.rootNode.addChildNode(dLight);
			
			this.skybox = new Skybox(this.camera.getEyeWorldTransform(this.rootNode).getMatrix().translation());
			//this.plane = new Plane(Settings.PlaneScale,this.camera,true);
			this.ground = new GroundBuilder(Settings.GroundScale,this.rootNode);			
			//this.sun = new Sun();
			this.rootNode.addChildNode(this.skybox);
			//this.rootNode.addChildNode(this.plane);
			//this.rootNode.addChildNode(this.sun);
			this.buildPipeline();
		}
		catch (Exception e) 
		{			
			e.printStackTrace();
		}
	}
	
	
	private void buildPipeline()
	{
		Printer.print(this.rootNode);
		Pipeline p = new Pipeline(this.rootNode);

	    p.setViewFrustumCullingMode(2);
	    
	    //Clear depth and color buffer, set the clear color to current background color
        p.clearBuffers(true, true, Color.BLACK); 
        
        //We are able to use more than one camera, set current
        p.switchCamera(this.camera);    
        p.setDepthTest(false);
        p.drawGeometry("SKYPASS", null);
        p.setDepthTest(true);       
        p.drawGeometry("AMBIENT", null);
      
        p.doLightLoop(true, true).drawGeometry("LIGHTING", null);
    
        this.pipeline = p;
	}
	
	
	private void setupCamera(float rX, float rY, float rZ) throws Exception
	{	
		//Aspect Ratio
		float ratio = 4.0f / 3.0f;
				
		this.camera = new CameraNode("Main cam", ratio, 60.0f);		
		this.camera.setTransform(Transform.translate(Settings.CamStartPosition));		
        this.rootNode.addChildNode(this.camera);
	}
	
	public GroundBuilder getGround() 
	{ 
		return this.ground; 
	}
	
	public Cloud getCloud() 
	{ 
		return this.cloud;
	}
	
	public Plane getPlane() 
	{
		return this.plane;
	}

	public void setPlane(Plane plane) 
	{
		this.plane = plane;
	}	
	
	public Pipeline getPipeline() 
	{
		return this.pipeline;
	}	
	
	public GroupNode getRootNode()
	{
		return rootNode;
	}

	public void setRootNode(GroupNode rootNode)
	{
		this.rootNode = rootNode;
	}

	public CameraNode getCamera() 
	{
		return camera;
	}

	public void setCamera(CameraNode camera)
	{
		this.camera = camera;
	}

	public PipelineCommandPtr getPtr()
	{
		return ptr;
	}

	public void setPtr(PipelineCommandPtr ptr)
	{
		this.ptr = ptr;
	}

    public int getHeight()
    {
        return height;
    }
	
	
	
	
}
